package com.qding.park.adapter.ark.adapter.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qding.park.adapter.ark.adapter.config.ARKConfig;
import com.qding.park.adapter.ark.adapter.constant.ArkConstant;
import com.qding.park.adapter.ark.adapter.constant.MethodConstant;
import com.qding.park.adapter.ark.adapter.entity.ResponseMsg;
import com.qding.park.adapter.ark.adapter.enums.RespCodeEnums;
import com.qding.park.adapter.ark.adapter.util.Helper;
import com.qding.park.common.core.exceptions.ExceptionMessage;
import com.qding.park.common.core.exceptions.business.adapter.AdapterException;
import com.qding.park.common.core.exceptions.system.NetWorkException;
import com.qding.park.common.core.network.HttpUtil;
import com.qding.park.common.utils.ftp.Ftp;
import com.qding.park.common.utils.string.StringUtil;
import com.qding.park.target.common.adapter.BaseDataAdapter;
import com.qding.park.target.common.entity.AdParkInfo;
import com.qding.park.target.common.entity.AdUserInfo;

/**
 * @ClassName BaseDataAdapterImpl
 * @Description TODO(基础数据同步 -- 方舟实现)
 * @author LeiYang
 * @Date 2017年5月8日 下午3:50:02
 * @version 1.0.0
 */
@Service("baseDataAdapter_13")
public class BaseDataAdapterImpl {

    private static final Logger _log = LoggerFactory.getLogger(BaseDataAdapterImpl.class);

    /**
     * @Field @fileSeparator : TODO(系统路径分隔符)
     */
    private static final String fileSeparator = System.getProperty("file.separator");

    /**
     * @Field @USER_FILE_PREFIX : TODO(用户信息文件前缀)
     */
    public static final String USER_FILE_PREFIX = "owner_info";

    /**
     * @Field @CAR_FILE_PREFIX : TODO(车辆信息文件前缀)
     */
    public static final String CAR_FILE_PREFIX = "car";

    /**
     * @Field @CAR_OWNER_PREFIX : TODO(车账号文件前缀)
     */
    public static final String CAR_OWNER_PREFIX = "car_owner";

    /**
     * @Field @FEE_STANDARD : TODO(临停收费标准文件前缀)
     */
    public static final String FEE_STANDARD = "fee_standard";
    
    /**
     * @Field @PARK_FEE : TODO(临停费项标准信息)
     */
    public static final String PARK_FEE = "park_fee";

    /**
     * @Field @FEE_STANDARD_INERVAL : TODO(区间/阶梯单价表)
     */
    public static final String FEE_STANDARD_INERVAL = "fee_standard_interval";

    /**
     * @Field @DATA_FILE_PATH : TODO(数据文件存放目录)
     */
    private static final String DATA_FILE_PATH = "baseData";

    /**
     * @Field @pageSize : TODO(分页查询的页长度)
     */
    private static final int pageSize = 100;

    private Ftp connectFtp() throws IOException {
        Ftp ftp = new Ftp();
        String hostname = ARKConfig.getAdapterFtpIp();
        int port = ARKConfig.getAdapterFtpPort();
        String username = ARKConfig.getAdapterFtpUser();
        String password = ARKConfig.getAdapterFtpPw();
        _log.info("hostname:{},port:{},username:{},password:{}" + hostname, port, username, password);
        ftp.connect(hostname, port, username, password);
        return ftp;
    }

    private File download(Ftp ftp, String remotePath, String remoteName) throws IOException {
        OutputStream out = null;
        try {
            String filepath = DATA_FILE_PATH + fileSeparator + UUID.randomUUID().toString();
            File downFile = new File(filepath, remoteName);
            out = FileUtils.openOutputStream(downFile);
            // 切换目前
            ftp.changeWorkingDirectory(remotePath);
            if (ftp.download(remoteName, out)) {
                return downFile;
            } else {
                return null;
            }
        } finally {
            out.close();
        }
    }

    private List<File> download(Ftp ftp, String remotePath, FTPFile[] ftpFiles) throws IOException {
        OutputStream out = null;
        try {
            List<File> files = new ArrayList<File>();
            String uuid = UUID.randomUUID().toString();
            String filepath = DATA_FILE_PATH + fileSeparator + uuid;
            // 切换目前
            ftp.changeWorkingDirectory(remotePath);
            for (FTPFile ftpFile : ftpFiles) {
                String remoteName = ftpFile.getName();
                File downFile = new File(filepath, remoteName);
                out = FileUtils.openOutputStream(downFile);
                if (ftp.download(remoteName, out)) {
                    files.add(downFile);
                    out.close();
                    out = null;
                }
            }

            return files;

        } finally {
            if(out!=null){
                out.close();
            }
           
        }
    }

    private File getInitFile(final String filePrefix) {
        String adapterFilepathInit = ARKConfig.getAdapterFilepathInit();
        Ftp ftp = null;
        try {
            ftp = connectFtp();
            FTPFile[] ftpFiles = ftp.listFiles(ARKConfig.getAdapterFilepathInit(), new FTPFileFilter() {

                @Override
                public boolean accept(FTPFile file) {
                    String fileName = file.getName();

                    String rexEl = "^" + filePrefix + "_" + ArkConstant.filedayFormregEx;
                    return StringUtil.regEx(fileName, rexEl) ? true : false;
                }

            });

            if (ftpFiles.length >= 1) {
                FTPFile ftpfile = ftpFiles[0];
                _log.debug(ftpfile.getName());
                String remoteName = ftpfile.getName();
                File downfile = download(ftp, adapterFilepathInit, remoteName);
                return downfile;
            } else {
                return null;
            }
        } catch (IOException e) {
            _log.error(e.getMessage(), e);
            ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                    AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), "方舟ftp连接失败",
                    "getUserInfoInitFile--方舟ftp连接失败");

            throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), e, exceptionMessage);
        } finally {
            try {
                ftp.disconnect();
            } catch (IOException e) {
                _log.error(e.getMessage(), e);
            }
        }
    }

    private File getDayFile(final String filePrefix) {
        String adapterFilepathInit = ARKConfig.getAdapterFilepathInit();
        Ftp ftp = null;
        try {
            ftp = connectFtp();
            FTPFile[] ftpFiles = ftp.listFiles(ARKConfig.getAdapterFilepathInit(), new FTPFileFilter() {

                @Override
                public boolean accept(FTPFile file) {
                    String fileName = file.getName();

                    return fileName.startsWith(filePrefix) ? true : false;
                }

            });

            if (ftpFiles.length >= 1) {
                FTPFile ftpfile = ftpFiles[0];
                _log.debug(ftpfile.getName());
                String remoteName = ftpfile.getName();
                File downfile = download(ftp, adapterFilepathInit, remoteName);
                return downfile;
            } else {
                return null;
            }
        } catch (IOException e) {
            _log.error(e.getMessage(), e);
            ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                    AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), "方舟ftp连接失败",
                    "getUserInfoInitFile--方舟ftp连接失败");

            throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), e, exceptionMessage);
        } finally {
            try {
                ftp.disconnect();
            } catch (IOException e) {
                _log.error(e.getMessage(), e);
            }
        }
    }

    public List<File> getAllDayFile(final String filePrefix) {
        String adapterFilepathDay = ARKConfig.getAdapterFilepathDay();
        Ftp ftp = null;
        try {
            ftp = connectFtp();
            FTPFile[] ftpFiles = ftp.listFiles(ARKConfig.getAdapterFilepathInit(), new FTPFileFilter() {

                @Override
                public boolean accept(FTPFile file) {
                    String fileName = file.getName();
                    String rexEl = "^" + filePrefix + "_" + ArkConstant.filedayFormregEx;
                    return StringUtil.regEx(fileName, rexEl) ? true : false;
                }

            });
            if (ftpFiles.length >= 1) {
                // 下载文件列表
                return download(ftp, adapterFilepathDay, ftpFiles);
            }
            return null;
        } catch (IOException e) {
            _log.error(e.getMessage(), e);
            ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                    AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), "方舟ftp连接失败",
                    "getUserInfoInitFile--方舟ftp连接失败");

            throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), e, exceptionMessage);
        } finally {
            try {
                ftp.disconnect();
            } catch (IOException e) {
                _log.error(e.getMessage(), e);
            }
        }
    }
    
    
    private List<File> getSameDayFile(final String filePrefix,final List<String> timeStrs) {
        String adapterFilepathDay = ARKConfig.getAdapterFilepathDay();
        Ftp ftp = null;
        try {
            ftp = connectFtp();
            FTPFile[] ftpFiles = ftp.listFiles(ARKConfig.getAdapterFilepathInit(), new FTPFileFilter() {

                @Override
                public boolean accept(FTPFile file) {
                    String fileName = file.getName();
                    String timename = fileName.substring(0,fileName .lastIndexOf("."));//去掉后缀名
                    String fileTag=fileName.substring(0,fileName.lastIndexOf("_"));
                    String timestr=timename.substring(timename.lastIndexOf("_")+1);
                    boolean tag=timeStrs.contains(timestr)&&fileTag.equals(filePrefix);
                    return tag?true:false;
                }

            });
            if (ftpFiles.length >= 1) {
                // 下载文件列表
                return download(ftp, adapterFilepathDay, ftpFiles);
            }
            return null;
        } catch (IOException e) {
            _log.error(e.getMessage(), e);
            ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                    AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), "方舟ftp连接失败",
                    "getUserInfoInitFile--方舟ftp连接失败");

            throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), e, exceptionMessage);
        } finally {
            try {
                ftp.disconnect();
            } catch (IOException e) {
                _log.error(e.getMessage(), e);
            }
        }
    }

    /**
     * @Description (TODO获取用户信息 初始化文件)
     * @return
     */
    public File getUserInfoInitFile() {
        return getInitFile(USER_FILE_PREFIX);
    }

    /**
     * @Description (TODO获取用户信息 日增量文件)
     * @param dayPrefix
     *            日期字符串 2017-09-09
     * @return
     */
    public File getUserInfoDayFile(String dayPrefix) {
        return getDayFile(USER_FILE_PREFIX + "_" + dayPrefix);
    }

    /**
     * @Description (TODO获取车辆初始化文件)
     * @return
     */
    public File getCarInitFile() {
        return getInitFile(CAR_FILE_PREFIX);
    }

    /**
     * @Description (TODO获取车辆信息日增量文件)
     * @param dayPrefix
     *            日期字符串 2017-09-09
     * @return
     */
    public File getCarDayFile(String dayPrefix) {
        return getDayFile(CAR_FILE_PREFIX + "_" + dayPrefix);
    }

    /**
     * @Description (TODO获取车账号初始化信息文件)
     * @return
     */
    public File getCarOwnerInitFile() {
        return getInitFile(CAR_OWNER_PREFIX);
    }

    /**
     * @Description (TODO车账号日增量文件)
     * @param dayPrefix
     *            日期字符串 2017-09-09
     * @return
     */
    public File getCarOwnerDayFile(String dayPrefix) {
        return getDayFile(CAR_OWNER_PREFIX + "_" + dayPrefix);
    }

    /**
     * @Description (TODO临停收费标准初始化文件)
     * @return
     */
    public File getFeeStandardInitFile() {
        return getInitFile(FEE_STANDARD);
    }
    
    /**
     * @Description (TODO临停费项标准信息)
     * @return
     */
    public File getParkFeeInitFile() {
        return getInitFile(PARK_FEE);
    }

    /**
     * @Description (TODO临停收费标准日增量文件)
     * @param dayPrefix
     *            日期字符串 2017-09-09
     * @return
     */
    public File getFeeStandardDayFile(String dayPrefix) {
        return getDayFile(FEE_STANDARD + "_" + dayPrefix);
    }

    /**
     * @Description (TODO区间/阶梯单价表 初始化文件)
     * @return
     */
    public File getFeeStandardIntervalInitFile() {
        return getInitFile(FEE_STANDARD_INERVAL);
    }

    /**
     * @Description (TODO区间/阶梯单价表 日增量文件文件)
     * @param dayPrefix
     *            日期字符串 2017-09-09
     * @return
     */
    public File getFeeStandardIntervalDayFile(String dayPrefix) {
        return getDayFile(FEE_STANDARD + "_" + dayPrefix);
    }

//    public List<File> getAllDayFile(String filePrefix){
//        
//    }
    
    /**
     * @Description (TODO下载并返所有用户日增量文件列表)
     * @return
     */
    public List<File> getAllOwnerDayFile() {
        return getAllDayFile(this.USER_FILE_PREFIX);
    }
    
    /**
     * @Description (TODO下载并返所有车辆日增量文件列表)
     * @return
     */
    public List<File> getAllCarDayFile() {
        return getAllDayFile(this.CAR_FILE_PREFIX);
    }
    
    /**
     * @Description (TODO下载并返所有车账号日增量文件列表)
     * @return
     */
    public List<File> getAllCarOwnerDayFile() {
        return getAllDayFile(this.CAR_OWNER_PREFIX);
    }
    
    /**
     * @Description (TODO下载并返所有临停计费规则日增量文件列表)
     * @return
     */
    public List<File> getAllFeerDayFile() {
        return getAllDayFile(this.FEE_STANDARD);
    }
    
    
    /**
     * @Description (TODO下载并返所有区间/阶梯单日增量文件列表)
     * @return
     */
    public List<File> getAllFeeInterrDayFile() {
        return getAllDayFile(this.FEE_STANDARD_INERVAL);
    }

    public List<File>   getDayFile(String filePrefix,List<String> timesstrs){
        if(filePrefix.equals(this.CAR_FILE_PREFIX)){
            return getCarDayFile(timesstrs);
        }else if(filePrefix.equals(this.USER_FILE_PREFIX)){
            return getOwnerDayFile(timesstrs);
        }else if(filePrefix.equals(this.CAR_OWNER_PREFIX)){
            return getCarOwnerDayFile(timesstrs);
        }else if(filePrefix.equals(this.FEE_STANDARD)){
            return getFeeDayFile(timesstrs);
        }else if(filePrefix.equals(this.FEE_STANDARD_INERVAL)){
            return getFeeIntervalDayFile(timesstrs);
        }else if(filePrefix.equals(this.PARK_FEE)){
            return getParkFeeDayFile(timesstrs);
        }else{
            return null;
        }
    }
    
    /**
     * @Description (TODO根据日期列表,获取日期列表用户文件)
     * @param timestrs 日期列表
     * @return
     */
    public List<File>  getOwnerDayFile(List<String> timesstrs){
       return  getSameDayFile(USER_FILE_PREFIX,timesstrs);
    }
    
    /**
     * @Description (TODO根据日期列表,获取日期列表车辆文件)
     * @param timestrs 日期列表
     * @return
     */
    public List<File>  getCarDayFile(List<String> timesstrs){
       return  getSameDayFile(this.CAR_FILE_PREFIX,timesstrs);
    }
    
    /**
     * @Description (TODO根据日期列表,获取日期列表车账号文件)
     * @param timestrs 日期列表
     * @return
     */
    public List<File>  getCarOwnerDayFile(List<String> timesstrs){
       return  getSameDayFile(CAR_OWNER_PREFIX,timesstrs);
    }
    
    /**
     * @Description (TODO根据日期列表,获取日期列表临停计费标准文件)
     * @param timestrs 日期列表
     * @return
     */
    public List<File>  getFeeDayFile(List<String> timesstrs){
       return  getSameDayFile(FEE_STANDARD,timesstrs);
    }
    
    /**
     * @Description (TODO根据日期列表,获取日期列表区间/阶梯文件)
     * @param timestrs 日期列表
     * @return
     */
    public List<File>  getFeeIntervalDayFile(List<String> timesstrs){
       return  getSameDayFile(FEE_STANDARD_INERVAL,timesstrs);
    }
    
    public List<File>  getParkFeeDayFile(List<String> timesstrs){
        return  getSameDayFile(PARK_FEE,timesstrs);
     }


    /**
     * @Description (TODO方舟 查询所有的车场信息)
     * @return
     */
    public List<AdParkInfo> getParkList() {
        String url = ARKConfig.getAdapterUrl();
        String urlMethod = Helper.createUrlAddress(url, MethodConstant.GET_PARK_LIST_PAGE);

        List<AdParkInfo> parkList = new ArrayList<AdParkInfo>();

        Map<String, String> params = new HashMap<String, String>();
        int pageNum = 1;
        params.put("pageNum", String.valueOf(pageNum));
        params.put("pageSize", String.valueOf(pageSize));

        try {
            String result = HttpUtil.doPost(urlMethod, params);
            ResponseMsg response = Helper.analysisResponse(result);

            if (!RespCodeEnums.SUCCESS.getValue().equals(response.getCode())) {
                // 失败
                ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                        AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), response.getMsg(), "方舟分页查询车场列表异常");

                throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), null,
                        exceptionMessage);
            }

            JSONObject data = (JSONObject) response.getData();
            JSONArray dataArray = data.getJSONArray("parkList");
            int totalCount = data.getIntValue("totalCount");
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject jsonObj = dataArray.getJSONObject(i);
                String parkId = jsonObj.getString("parkId");
                String parkName = jsonObj.getString("parkName");
                String projectId = jsonObj.getString("projectId");
                AdParkInfo parkInfo = new AdParkInfo();
                parkInfo.setParkCode(parkId);
                parkInfo.setParkName(parkName);
                parkInfo.setProjectId(projectId);
                parkList.add(parkInfo);
            }

            while (totalCount > pageNum * pageSize) {
                Map<String, String> params1 = new HashMap<String, String>();
                params1.put("pageNum", String.valueOf(++pageNum));
                params1.put("pageSize", String.valueOf(pageSize));
                ResponseMsg resp = Helper.analysisResponse(result);
                if (!RespCodeEnums.SUCCESS.getValue().equals(response.getCode())) {
                    // 失败
                    ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                            AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), response.getMsg(),
                            "方舟分页查询车场列表异常");
                    throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), null,
                            exceptionMessage);
                }

                JSONObject data1 = (JSONObject) resp.getData();
                JSONArray dataArray1 = data1.getJSONArray("parkList");
                totalCount = data.getIntValue("totalCount");
                for (int i = 0; i < dataArray.size(); i++) {
                    JSONObject jsonObj = dataArray.getJSONObject(i);
                    String parkId = jsonObj.getString("parkId");
                    String parkName = jsonObj.getString("parkName");
                    String projectId = jsonObj.getString("projectId");
                    AdParkInfo parkInfo = new AdParkInfo();
                    parkInfo.setParkCode(parkId);
                    parkInfo.setParkName(parkName);
                    parkInfo.setProjectId(projectId);
                    parkList.add(parkInfo);
                }
            }

            return parkList;

        } catch (NetWorkException | IOException e) {
            _log.error(e.getMessage(), e);
            ExceptionMessage exceptionMessage = ExceptionMessage.createExceptionMessage(
                    AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getDesc(), "方舟接口网络暖异常", "方舟分页查询车场列表异常");
            throw new AdapterException(AdapterException.TypeEnum.EXCEPTION_ADAPTER_FAIL.getId(), e, exceptionMessage);
        }

    }

}
